/*
 * Copyright (c) 2018. All  rights reserved.
 * 项目名：microservice-office
 * 文件名：FileUtils.java
 * Date  ：18-3-30 下午1:25
 * Author：abin
 *
 */

package com.stadium.common.utils;

import com.stadium.common.config.ConfigProperties;
import com.stadium.common.enums.ResultEnum;
import com.stadium.common.exception.RRException;
import com.stadium.dto.FileDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;

@Component
public class FileUtils {

    private static final Logger logger = LoggerFactory.getLogger(FileUtils.class);

    @Autowired
    private ConfigProperties configPropertiesAutowired;
    private static ConfigProperties configProperties;

    @PostConstruct
    public void init() {
        configProperties = this.configPropertiesAutowired;
    }

    /**
     * 复制单个文件
     *
     * @param oldPath String 原文件路径 如：c:/fqf.txt
     * @param newPath String 复制后路径 如：f:/fqf.txt
     * @return boolean
     */
    public static void copyFile(String oldPath, String newPath) {
        try {
            int bytesum = 0;
            int byteread = 0;
            File oldfile = new File(oldPath);
            File newFile = new File(newPath);
            File fileParent = newFile.getParentFile();
            if (!fileParent.exists()) {
                fileParent.mkdirs();
            }
            newFile.createNewFile();
            if (oldfile.exists()) { //文件存在时
                InputStream inStream = new FileInputStream(oldPath); //读入原文件
                FileOutputStream fs = new FileOutputStream(newPath);
                byte[] buffer = new byte[1444];
                int length;
                while ((byteread = inStream.read(buffer)) != -1) {
                    bytesum += byteread; //字节数 文件大小
                    fs.write(buffer, 0, byteread);
                }
                inStream.close();
                fs.close();
            }
        } catch (Exception e) {
            System.out.println("复制单个文件操作出错");
            e.printStackTrace();
        }
    }

    public static FileDto uploadFile(MultipartFile file, String serviceName) throws RRException {
        FileDto fileDto = new FileDto();
        // 获取上传文件的原始名
        String fileName = null;
        try {
            fileName = new String(file.getOriginalFilename().getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            throw new RRException(e.getMessage());
        }
        // 对文件重命名并保持原格式
        //获得文件格式进行判断
        String fileTypeResult = fileType(fileName);
        //获得文件后缀名
        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()).toLowerCase();
        String originalFilename = fileName.substring(0, fileName.lastIndexOf("."));
        if (!fileTypeResult.equals("文件名为空!") || !fileTypeResult.equals("其他")) {
            String fileSizeResult = fileSize(fileTypeResult, file);
            if (fileSizeResult.equals("文件大小适合")) {
                fileName = String.valueOf(System.currentTimeMillis()) + "." + fileType;
                // 获取文件存储路径
                String path = configProperties.getUploadFileUrl() + configProperties.getFileUrl()+ configProperties.getUploadFileSymbol() + serviceName;
                File fileF = new File(path);
                // 判断上传文件的保存目录是否存在
                if (!fileF.exists()) {
                    // 创建目录
                    fileF.mkdirs();
                }
                try {
                    file.transferTo(new File(path + configProperties.getUploadFileSymbol() + fileName));// ();
                } catch (IOException e) {
                    throw new RRException(e.getMessage());
                }
                if (fileTypeResult.equals("图片")) {
                    PicUtils.commpressPicForScale(path + configProperties.getUploadFileSymbol() + fileName, path + configProperties.getUploadFileSymbol() + fileName, 500, 0.8);
                }
                String filePath = configProperties.getFileUrl()  + configProperties.getUploadFileSymbol() + serviceName + configProperties.getUploadFileSymbol() + fileName;
                String fileStoragePath = configProperties.getUploadFileUrl()+configProperties.getFileUrl()  + configProperties.getUploadFileSymbol() + serviceName + configProperties.getUploadFileSymbol() + fileName;
                fileDto.setFileStoragePath(fileStoragePath);
                fileDto.setFileName(fileName);
                fileDto.setFilePath(filePath);
            } else {
                throw new RRException(ResultEnum.FILE_EXCEEDED_LIMIT.getMsg());
            }
        } else {
            throw new RRException(ResultEnum.FILE_TYPE_MISMATCH.getMsg());
        }

        return fileDto;
    }

    public static String fileType(String fileName) {
        if (fileName == null) {
            fileName = "文件名为空！";
            return fileName;
        } else {
            // 获取文件后缀名并转化为写，用于后续比较
            String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()).toLowerCase();
            // 创建图片类型数组
            String img[] = {"bmp", "jpg", "jpeg", "png", "tiff", "gif", "pcx", "tga", "exif", "fpx", "svg", "psd",
                    "cdr", "pcd", "dxf", "ufo", "eps", "ai", "raw", "wmf"};
            for (int i = 0; i < img.length; i++) {
                if (img[i].equals(fileType)) {
                    return "图片";
                }
            }
            // 创建文档类型数组
            String document[] = {"txt", "doc", "docx", "xls", "xlsx", "pdf", "ppt", "pptx"};
            for (int i = 0; i < document.length; i++) {
                if (document[i].equals(fileType)) {
                    return "文档";
                }
            }
            // 创建视频类型数组
            String video[] = {"mp4", "avi", "mov", "wmv", "asf", "navi", "3gp", "mkv", "f4v", "rmvb", "webm"};
            for (int i = 0; i < video.length; i++) {
                if (video[i].equals(fileType)) {
                    return "视频";
                }
            }
            // 创建音乐类型数组
            String music[] = {"mp3", "wma", "wav", "mod", "ra", "cd", "md", "asf", "aac", "vqf", "ape", "mid", "ogg",
                    "m4a", "vqf"};
            for (int i = 0; i < music.length; i++) {
                if (music[i].equals(fileType)) {
                    return "音乐";
                }
            }
            // 创建压缩包类型数组
            String Archive[] = {"rar", "zip"};
            for (int i = 0; i < music.length; i++) {
                if (Archive[i].equals(fileType)) {
                    return "压缩包";
                }
            }
        }
        return "其他";
    }

    public static String fileSize(String fileType, MultipartFile file) {
        Long fileSzie = file.getSize();

        if (fileType.equals("图片") & fileSzie < 10 * 1024 * 1024l) {
            return "文件大小适合";
        } else if (fileType.equals("文档") & fileSzie < 50 * 1024 * 1024l) {
            return "文件大小适合";
        } else if (fileType.equals("视频") & fileSzie < 500 * 1024 * 1024l) {
            return "文件大小适合";
        } else if (fileType.equals("音乐") & fileSzie < 10 * 1024 * 1024l) {
            return "文件大小适合";
        } else if (fileType.equals("压缩包") & fileSzie < 500 * 1024 * 1024l) {
            return "文件大小适合";
        } else {
            return "文件超过限制";
        }
    }

    public static String fileMemory(Long fileSzie) {
        if (fileSzie < 1024) {
            return String.valueOf(fileSzie) + "B";
        } else {
            fileSzie = fileSzie / 1024;
        }
        //如果原字节数除于1024之后，少于1024，则可以直接以KB作为单位
        //因为还没有到达要使用另一个单位的时候
        //接下去以此类推
        if (fileSzie < 1024) {
            return String.valueOf(fileSzie) + "KB";
        } else {
            fileSzie = fileSzie / 1024;
        }
        if (fileSzie < 1024) {
            //因为如果以MB为单位的话，要保留最后1位小数，
            //因此，把此数乘以100之后再取余
            fileSzie = fileSzie * 100;
            return String.valueOf((fileSzie / 100)) + "."
                    + String.valueOf((fileSzie % 100)) + "MB";
        } else {
            //否则如果要以GB为单位的，先除于1024再作同样的处理
            fileSzie = fileSzie * 100 / 1024;
            return String.valueOf((fileSzie / 100)) + "."
                    + String.valueOf((fileSzie % 100)) + "GB";
        }
    }

    /**
     * @return
     */
    public static String delFile(String filePath) {
        String filePathStr = configProperties.getUploadFileUrl() + filePath;
        File file = new File(filePathStr);
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                return "1";
            } else {
                return "2";
            }
        } else {
            return "3";
        }

    }

    public static void downFile(String fileUrl, String fileName) throws Exception {
        URL url = new URL(fileUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(5 * 1000);
        //通过输入流获取图片数据
        if (conn.getResponseCode() != 400) {
            InputStream inStream = conn.getInputStream();
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outStream.write(buffer, 0, len);
            }
            inStream.close();
            byte[] btImg = outStream.toByteArray();
            if (null != btImg && btImg.length > 0) {
                File file = new File(fileName.replaceAll(" ", ""));
                FileOutputStream fops = new FileOutputStream(file);
                fops.write(btImg);
                fops.flush();
                fops.close();
            } else {
                System.out.println("没有从该连接获得内容");
            }
        }
    }


    public static byte[] downFile(String fileUrl) throws Exception {
        URL url = new URL(fileUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(5 * 1000);
        //通过输入流获取图片数据
        if (conn.getResponseCode() != 400) {
            InputStream inStream = conn.getInputStream();
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outStream.write(buffer, 0, len);
            }
            inStream.close();
            byte[] btImg = outStream.toByteArray();
            if (null != btImg && btImg.length > 0) {
                return btImg;
            } else {
                System.out.println("没有从该连接获得内容");
            }
        }
        return null;
    }

    public static InputStream downFileInputStream(String fileUrl) throws Exception {
        URL url = new URL(fileUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(5 * 1000);
        //通过输入流获取图片数据
        if (conn.getResponseCode() != 400) {
            InputStream inStream = conn.getInputStream();
            return inStream;
        } else {
            System.out.println("没有从该连接获得内容");
        }
        return null;
    }

    public static byte[] inputStreamToByte(InputStream inputStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inputStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
        }
        byte[] btImg = outStream.toByteArray();
        if (null != btImg && btImg.length > 0) {
            return btImg;
        } else {
            throw new RRException("inputStreamToByte转化失败！");
        }
    }


    /**
     * 先根遍历序递归删除文件夹
     *
     * @param dirFile 要被删除的文件或者目录
     * @return 删除成功返回true, 否则返回false
     */
    public static boolean deleteFile(File dirFile) {
        // 如果dir对应的文件不存在，则退出
        if (!dirFile.exists()) {
            return false;
        }

        if (dirFile.isFile()) {
            return dirFile.delete();
        } else {

            for (File file : dirFile.listFiles()) {
                deleteFile(file);
            }
        }

        return dirFile.delete();
    }

    /**
     * 根据byte数组，生成文件
     * filePath  文件路径
     * fileName  文件名称（需要带后缀，如*.jpg、*.java、*.xml）
     */
    public static void getFile(byte[] bfile, String filePath, String fileName) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = new File(filePath);
            if (!dir.exists() && !dir.isDirectory()) {//判断文件目录是否存在
                dir.mkdirs();
            }
            file = new File(filePath + File.separator + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bfile);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    public static List<File> func(File file, List<File> fileList) {
        File[] fs = file.listFiles();
        for (File f : fs) {
            //若是目录，则递归打印该目录下的文件
            if (f.isDirectory()) {
                func(f, fileList);
            }
            //若是文件，直接打印
            if (f.isFile()) {
                fileList.add(f);
            }
        }
        return fileList;
    }

}
